//: Playground - noun: a place where people can play

import UIKit

var str = "Hello, playground"

//:  类型嵌套
// 可以在允许类型嵌套的类型中嵌套枚举 类 结构体,并且支持多层嵌套


//:  值类型的嵌套
struct NestedStruct {
    enum enumType1: Character {         // 在结构体中嵌套枚举
        case enumValue1 = "A", enumValue2 = "B", enumValue3 = "C"
    }
    enum enumType2: Int {
        case two = 2, three, four
        struct Values {                 // 枚举中嵌套结构体
            enum num: Int {             // 结构体中再嵌套枚举
                case num1 = 1, num2, num3
            }
        }
    }
}

// 枚举和结构体都是值类型,直接通过类型名称调用
print(NestedStruct.enumType1.enumValue2.rawValue) // B
print(NestedStruct.enumType2.Values.num.num2.rawValue) // 2


//:  引用类型嵌套
class ClassType1 {
    class ClassType2 {
        func hello() -> String {
            return "Hello"
        }
    }
    enum enumType2:Int {// 引用类型中嵌套值类型
        case two = 2,three,four
        struct Values {
            enum num:Int {
                case num1 = 1,num2,num3
            }
        }
    }
}
let someClass = ClassType1.ClassType2() // 引用类型嵌套也是在类型名前面加外部类型的类型名
print(someClass.hello())                // Hello
print(ClassType1.enumType2.Values.num.num1.rawValue) // 1


//:  扩展: 可以为已有的类 结构体 枚举或者协议类型添加新功能,类似OC的分类
// swift中可以扩展的功能:  1. 为已有类型扩展计算型实例属性和计算型类型属性
//                      2. 为已有类型添加新的便利构造器
//                      3. 为已有类型添加新的实例方法和类型方法
//                      4. 为已有类型添加新下标
//                      5. 为已有的类 结构体 枚举添加新的嵌套类型


// 扩展语法
//class SomeClass {                       // 定义一个要扩展的SomeClass类
//}
//extension SomeClass: someProtocol {     // 在类名前面添加extension关键字,冒号后面写协议名
//    // 扩展功能,协议实现写在这里
//}



//:  用扩展为已有类型添加计算型实例属性和计算型类型属性
extension Double {                      // 为double添加计算型实例属性
    var m: Double { return self }       // 只读计算型属性可以省略get
    var cm: Double { return self / 100.0 } // 将单位长度换算成米并返回
    var mm: Double { return self / 1000.0 }
    
//    var invalid: Double?                // ❌, 扩展不能添加存储属性和属性观察器
}

let oneMeter = 100.cm
let centimetreMetre = 10.mm
print("100cm=\(oneMeter)米,10mm=\(centimetreMetre)米") // 100cm=1.0米,10mm=0.01米


//:  扩展可以为已有类型添加新的便利构造器,但不能添加新的指定构造器和析构器
struct Size {                           // 定义尺寸
    var width = 0.0, height = 0.0
}
struct Point {                          // 定义位置
    var x = 0.0, y = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
}

let rect1 = Rect()
// 通过逐一构造器和默认构造器为实例赋值
let rect2 = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 3.0, height: 3.0))

// 如果使用构造器为值类型添加构造器时,该值类型原始实现中未定义任何定制的构造器且所有存储属性提供了默认值,
// 这时就可以在扩展中的构造器里调用默认构造器和逐一成员构造器.
extension Rect {                        // 接受指定中心点和大小的构造器来扩展Rect结构体
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))
print(centerRect.origin)                // Point(x: 2.5, y: 2.5), 获得Point位置


//:  通过扩展可以为已有类型添加新的实例方法和类型方法
extension Int {                         // 为Int类型添加一个实例方法
    func repetitions(task: () -> Void) { // 根据Int值来决定循环的次数
        for _ in 0 ..< self {
            task()
        }
    }
}
4.repetitions {
    print("Four")                       // 打印四次
}


extension Int {                         // 通过扩展实例方法修改实例本身
    // 结构体和枚举是值类型,所以在改变实例本身的时候需要在方法前面加mutating关键字
    mutating func squ() {
        self = self * self
    }
}
var someInt = 3
someInt.squ()


//:  扩展可以为已有类型添加新下标
extension Int {
    subscript(digitIndex:Int) -> Int{// 返回从右往左第N位的数字
        var decimalBase = 1
        for _ in 0 ..< digitIndex{
            decimalBase *= 10
        }
        return (self/decimalBase) % 10
    }
}
print(13435361323542[2])
print(24321434235[7])


//:  可以为已有的类 结构体 枚举添加新的嵌套类型
extension Int {
    enum Kind {                         // Kind三种类型,负数,零,正数
        case Negative, Zero, Positive
    }
    var kind: Kind {                    // 根据实际值,返回Kind类型
        switch self {
        case 0:
            return .Zero
        case let x where x > 0:
            return .Positive
        default:
            return .Negative
        }
    }
}

func printIntegerKinds(numbers: [Int]) { // 接收一个数组,打印每个元素的Kind类型
    for number in numbers {
        switch number.kind {
        case .Negative:
            print("-", terminator: " ") // terminator: " " 表示不换行,并添加一个空格
        case .Zero:
            print("0", terminator: " ")
        case .Positive:
            print("+", terminator: " ")
        }
    }
    print("")                          // 换行
}

printIntegerKinds(numbers: [12, -4, 0, 32, -74, 2, 0, 12]) // + - 0 + - + 0 +



















